#include <stdio.h>
#include <packages.h>
#include <math.h>

#define lastMenu				3	 /* number of menus */
#define appleMenu			 1	 /* menu ID for desk accessory menu */
#define fileMenu				256	 /* menu ID for File menu */
#define editMenu				257	 /* menu ID for Edit menu */

#define maxvalue				512
#define maxvectsize		 8
short vscaling = 1;
#define hscaling				1


typedef double matrixtype[maxvectsize][maxvectsize];
typedef double vectortype[maxvectsize];
typedef char titletype[21];


typedef struct optiontype
	{
	Boolean start, quit, edit, newfile, debug;
} optiontype;

Rect Trect, dragRect;
EventRecord myEvent;
WindowPtr myWindow, whichWindow;
WindowRecord wRecord;
short code;
MenuHandle myMenus[lastMenu];	 /*Handles to all of the menus*/
DialogPtr theDialog;
optiontype options;

vectortype need, deltaneed, response, deltaresponse, alphavector,
			stimulation, consumvector, tempvct1, tempvct2;
matrixtype generalization, consumation, excitation, inhibition,
			tempmatrix, ident;
short vectSize, loop, stimuli;
double alpha, personality;
char answer;


/* procedure InitScreen;*/
/* begin*/
/*	HideAll;*/
/*	GetPort(dPort);*/
/*	GetDrawingRect(dRect);*/
/*	GetTextRect(TRect);*/
/*	SetRect(TextRect, 250, 30, 530, 250);*/
/*	SetRect(DrawRect, 5, 40, 700, 380);*/
/*	SetTextRect(TextRect);*/
/*	SetDrawingRect(DrawRect);*/
/*	ShowDrawing;*/
/*	ShowText;*/
/* end;*/

void SetUpMenus(void)
{
	short i;

	InitMenus ();
	myMenus[0] = GetMenu(appleMenu);
	AddResMenu(myMenus[0], 'DRVR');  /*add desk accessories*/
	myMenus[1] = GetMenu(fileMenu);
	myMenus[2] = GetMenu(editMenu);   /*not really used,  but just for practice*/
	for (i = 0; i <= lastMenu - 1; i++)
		InsertMenu(myMenus[i], 0);
	DrawMenuBar ();
}

void Startup(void)
{	 /*start initialization sequence*/
	/*basic initialization of MAC tools*/
	InitGraf(&thePort);        /*start initialization sequence*/
	InitFonts ();
	InitWindows ();
	TEInit ();
	InitDialogs(0L);

	SetUpMenus ();  /*throw menu bar up on the screen and insert menu items*/
	InitCursor ();  /*make cursor an arrow*/
	FlushEvents(everyEvent, 0);

	myWindow = GetNewWindow(256, &wRecord, (WindowPtr)-1L);/*show this one*/
	SetPort(myWindow);   /*graphics will go into my window*/

	/*Writelns and Readlns text will go to my window*/

	/*	 WWINIT;*/
	/*initialize the WritelnWindow unit*/
	/*not used anymore*/
	/*with Trect do*/
	/*begin*/
	/*top := 40;*/
	/*right := 480;*/
	/*bottom := 330;*/
	/*left := 40;*/
	/*end;*/
	/*GetFNum('Geneva', familyID);*/
	/*WWNew(Trect, 'Animals', false, true, 80, FamilyID, 9);*/
}

void matrixXvector(double *a, double (*b)[maxvectsize], double *c,
				short n, short m)
{
	/*A:= B C									A is a m dimensional vector*/
	/*B is a m x n dimensional matrix*/
	/*C is a n dimensional vector*/
	short i, j;
	double aij;

	for (i = 0; i <= n - 1; i++)
	{	 /*rows*/
		aij = 0.0;
		for (j = 0; j <= m - 1; j++)	 /*columns*/
			aij += b[i][j] * c[j];
		a[i] = aij;
	}
}	/*matrixXvector*/


void vectoradd(double *a, double *b, double *c, short n)
{
	/*A:=B+ C					 A,B,C are n dimensional vectors*/
	short i;

	for (i = 0; i <= n - 1; i++)
		a[i] = b[i] + c[i];
}


void vectorsubtract(double *a, double *b, double *c, short n)
{
	short i;

	for (i = 0; i <= n - 1; i++)
		a[i] = b[i] - c[i];
}


void vectorzero(double *a, short n)
{
	short i;

	for (i = 0; i <= n - 1; i++)
	{
		if (a[i] < 0.0)
			a[i] = 0.0;
	}
}


void VectorInit(double *a, short n)
{
	short i;

	for (i = 0; i <= n - 1; i++)
		a[i] = 0.0;
}


void vectordraw(double *a, double *b, short n, short loop,
					 short offset, short vscaling)
{
	short i, v, dv;

	for (i = 1; i <= n; i++)
	{
		if (a[i-1] == 0.0)
	{	 /*look out for zeroed out responses*/
			v = offset;
			dv = 0;
		} else
	{
			v = offset - ceil(a[i-1] * vscaling);
			dv = - ceil(b[i-1] * vscaling);
		}
		/* normal condition*/
		MoveTo(loop * (long) hscaling, v);
		PenSize(i, i);  /*change pen size to indicate which activity is occuring*/
		Line((long) hscaling, dv);
	}
}


void vectorread(double *a, short n, char *title)
{
	short i;

	printf("enter the %s vector\n", title);
	for (i = 0; i <= n - 1; i++)
		scanf("%lg", &a[i]);
	putchar('\n');
}


void scalarXvector(double *a, double s, double *b, short n)
{
	short i;

	for (i = 0; i <= n - 1; i++)
		a[i] = s * b[i];
}


void scalarXmatrix(double (*a)[maxvectsize], double s,
				double (*b)[maxvectsize], short n)
{
	short i, j;

	for (i = 0; i <= n - 1; i++)
	{
		for (j = 0; j <= n - 1; j++)
			a[i][j] = s * b[i][j];
	}
}


void matrixread(double (*a)[maxvectsize], short n, char *title)
{
	short i, j;

	printf("enter the %s matrix\n", title);
	for (i = 0; i <= n - 1; i++)
	{
		for (j = 0; j <= n - 1; j++)
			scanf("%lg", &a[i][j]);
		putchar('\n');
	}
}


void matrixwrite(double (*a)[maxvectsize], short n)
{
	short i, j;

	for (i = 0; i <= n - 1; i++)
	{
		for (j = 0; j <= n - 1; j++)
			printf("%5.2f", a[i][j]);
		putchar('\n');
	}
}


void identity(double (*temp)[maxvectsize], short vectSize)
{
	short i, j;

	for (i = 1; i <= vectSize; i++)
	{
		if (i > 1)
	{
			for (j = 0; j <= i - 2; j++)
			{
				temp[i-1][j] = 0.0;
				temp[j][i-1] = 0.0;
			}
		}
		temp[i-1][i-1] = 1.0;
	}
}


void DynamicSimulation(void)
{	/*dynamic*/
	/*the old program dynamic*/
	short stimuli, loop;
	char STR1[256];
	short FORLIM, FORLIM1;


	/*InitScreen;*/
	printf(" a model of reciprocal inhibition \n");
	/*write('enter alpha, personality ');*/
	/*readln(alpha, personality);*/
	alpha = 0.2;
	personality = 1.0;

	printf("do you want to specify the problem size? [no] \n");
	scanf("%c%*[^\n]", &answer);
	getchar();
	if (answer == '\n')
		answer = ' ';
	if (answer == 'y')
	{
		printf("enter the problem size	");
		scanf("%hd%*[^\n]", &vectSize);
		getchar();
	} else
		vectSize = 3;
	identity(ident, vectSize);
	printf("do you want to specify the stimulation vector? [no] \n");
	scanf("%c%*[^\n]", &answer);
	getchar();
	if (answer == '\n')
		answer = ' ';
	if (answer == 'y')
		vectorread(stimulation, vectSize, "stimulation");
	else
	{
		FORLIM = vectSize;
		for (stimuli = 1; stimuli <= vectSize; stimuli++)
			stimulation[stimuli-1] = stimuli * 0.5;
	}
	printf("do you want to specify the consummation matrix [no] \n");
	scanf("%c%*[^\n]", &answer);
	getchar();
	if (answer == '\n')
		answer = ' ';
	if (answer == 'y')
		matrixread(consumation, vectSize, "consummation");
	else
		scalarXmatrix(consumation, 0.2, ident, vectSize);
	printf("do you want to specify the excitation matrix [no] \n");
	scanf("%c%*[^\n]", &answer);
	getchar();
	if (answer == '\n')
		answer = ' ';
	if (answer == 'y')
		matrixread(excitation, vectSize, "excitation");
	else
		scalarXmatrix(excitation, alpha, ident, vectSize);
	printf("do you want to specify the inhibition matrix? [no] \n");
	scanf("%c%*[^\n]", &answer);
	getchar();
	if (answer == '\n')
		answer = ' ';
	if (answer == 'y')
		matrixread(inhibition, vectSize, "inhibition");
	else
	{
		for (loop = 0; loop <= vectSize - 1; loop++)
		{
			for (stimuli = 0; stimuli <= vectSize - 1; stimuli++)
				inhibition[loop][stimuli] = 1.0;
			inhibition[loop][loop] = 0.1;
		}
	}
	VectorInit(need, vectSize);
			/*zero out initial values of need and response*/
	VectorInit(response, vectSize);
	scalarXmatrix(generalization, personality, ident, vectSize);

	for (loop = 1; loop <= 25; loop++)	 /*clear the screen*/
		putchar('\n');
	ShowWindow (myWindow);
	SetPort (myWindow);
	SelectWindow (myWindow);
	MoveTo(0, 140);
	DrawString("\pNeeds");
	MoveTo(0, 250);
	DrawString("\pResponses");
	MoveTo(100, 30);
	DrawString("\pTime -->");

	/*begin the main loop*/
	for (loop = 1; loop <= maxvalue; loop++)
	{
		/*if loop = 250 then*/
		/*		ShowDrawing;*/
		matrixXvector(tempvct1, generalization, stimulation, vectSize, vectSize);
		matrixXvector(consumvector, consumation, response, vectSize, vectSize);

// 		if (! Button ())
// 			vectorread(stimulation, vectSize, "new stimulation");

		vectorsubtract(deltaneed, tempvct1, consumvector, vectSize);

		matrixXvector(tempvct1, inhibition, response, vectSize, vectSize);
		matrixXvector(tempvct2, excitation, need, vectSize, vectSize);

		vectorsubtract(deltaresponse, tempvct2, tempvct1, vectSize);

		vectordraw(need, deltaneed, vectSize, loop, 125, vscaling);

		vectoradd(need, need, deltaneed, vectSize);

		vectordraw(response, deltaresponse, vectSize, loop, 300, vscaling);

		vectoradd(response, response, deltaresponse, vectSize);

		vectorzero(response, vectSize);
	}
}	/*dynamic*/


/*the remaining code was added to allow for windows, menus, etc*/

void Message(short dialogNumber)
{	 /*save the current status of the screen display*/
	/*Throw up a Dialog Box and wait for keypress*/
	DialogPtr theDialog;
	EventRecord myEvent;
	short itemHit;
	GrafPtr tempPort;

	GetPort(tempPort);       /*save the current status of the screen display*/
	theDialog = GetNewDialog(dialogNumber, 0L, (WindowPtr)-1L); /*display dialog # */
	ModalDialog(0L, &itemHit); /*show the dialog and wait for a button*/
	DisposDialog(theDialog);  /*get rid of the dialog and show the screen*/
	SetPort(tempPort);        /*put back the original display*/
}




void DoCommand(long mResult, optiontype *options)
{
	/*process menu selection*/
	Str255 name;
	short theMenu, theItem, refNum;
	short AlertId = 1;

	theMenu = HiWord(mResult);
	theItem = LoWord(mResult);
	switch (theMenu)
	{

	case appleMenu:
		if (theItem == 1)	 /*throw up message window*/
			Message(1);
		else
			{
				GetItem(myMenus[0], theItem, &name);
				refNum = OpenDeskAcc(&name);
		}
		break;
		/*applemenu*/

	/*do a desk accessory*/
/* p2c: DYNAMIC.pas, line 396:
 * Warning: Too many arguments for built-in routine [225] */
	case fileMenu:
		switch (theItem)
		{

			case 1:
				DynamicSimulation ();
			break;

		case 2:
			options->debug = true;
			break;

		case 3:
			/* blank case */
			break;

		/* AlertNum:=CautionAlert(AlertId,nil);*/
		/*																If AlertNum=1 then*/
		/*																			 initialize;*/
		case 4:
			options->quit = true;
			break;
		}
		break;

	case editMenu:
		options->edit = true;
		break;


	}/*case theMenu*/
}	/*DoCommand*/


void WaitForCommand(void)
{
	/*get options from menu bar until start*/
	char theChar;

	options.start = false;
	options.debug = false;
	options.edit = false;
	options.newfile = false;
	options.quit = false;
	do
	{
		GetNextEvent(everyEvent, &myEvent);
		switch (myEvent.what)
		{
		case mouseDown:
			code = FindWindow(myEvent.where, &whichWindow);
			switch (code)
			{
				case inMenuBar:
					DoCommand(MenuSelect(myEvent.where), &options);
				break;

				case inSysWindow:
					SystemClick(&myEvent, whichWindow);
	break;

			case inDrag:
						DragWindow(whichWindow, myEvent.where, &dragRect);
	break;
			}/*case code*/
			break;
			/*mouse down*/

		case keyDown:
		case autoKey:	/*try processing a menu-key equivalent*/
			theChar = (myEvent.message & charCodeMask);	 /*the last byte*/
			if ((myEvent.modifiers & cmdKey) != 0)
	DoCommand(MenuKey(theChar), &options);
			break;
		}/*case myEvent.what*/

		if (options.start)
	{;
// 			DynamicSimulation();
// 			options.start = false;
		}
		if (options.edit)
	{	 /*repeat loop*/
			/* editfile;*/
			options.edit = false;
		}
	} while (!(options.quit || options.edit));	 /*set in DoCommand*/
}	/*waitfor command*/



void PutUpWindow(void)
{
	WindowPtr drawWindPtr;
	Point offSet;
	char STR[256];

	drawWindPtr = NewCWindow(0L, &screenBits.bounds, "\p", true, plainDBox, (WindowPtr)-1L,
				 false, 0L);
	SetPort (drawWindPtr);
}


main()
{
	Startup();	 /*various MAC type initializations*/
	/*PutUpWindow;*/
	putchar('\n');
			/*the screen initialization seems to start 1 line too high*/

	WaitForCommand();	 /*the Main Event Loop*/
}



/* End. */
